package com.hitqz.robot.biz.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.google.common.collect.Maps;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.TransStaticDateDto;
import com.hitqz.robot.api.business.dto.TransStaticYearDto;
import com.hitqz.robot.api.business.entity.RobotEntity;
import com.hitqz.robot.api.business.entity.RobotWarningRecordEntity;
import com.hitqz.robot.api.business.entity.TicketsEntity;
import com.hitqz.robot.api.business.params.HomeTicketsParams;
import com.hitqz.robot.api.business.params.SortByTypeParams;
import com.hitqz.robot.api.business.vo.*;
import com.hitqz.robot.biz.service.PatrolResultService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.biz.service.RobotWarningRecordService;
import com.hitqz.robot.biz.service.TicketsService;
import com.hitqz.robot.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author xupkun
 * @date 2024/12/2
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/home")
@Tag(name = "大屏-首页数据")
@Slf4j
public class HomeController {

    private final RobotService robotService;

    private final TicketsService ticketsService;

    private final RobotWarningRecordService robotWarningRecordService;

    private final PatrolResultService patrolResultService;

    @Operation(summary = "首页-异常数据统计" , description = "异常数据统计" )
    @GetMapping("/errorData" )
    public R<List<HomeErrorStaticDto>> errorData() {
        List<HomeErrorStaticDto> list = Lists.newArrayList();

        HomeErrorStaticDto errorStaticDto = new HomeErrorStaticDto();
        //errorStaticDto.setLabel("驱动器异常");
        //errorStaticDto.setNumber(10);
        //errorStaticDto.setPercent("6.89");
        //list.add(errorStaticDto);
        //
        //errorStaticDto = new HomeErrorStaticDto();
        //errorStaticDto.setNumber(30);
        //errorStaticDto.setLabel("导航异常");
        //errorStaticDto.setPercent("20");
        //list.add(errorStaticDto);
        //
        //
        //errorStaticDto = new HomeErrorStaticDto();
        //errorStaticDto.setNumber(13);
        //errorStaticDto.setLabel("取油异常");
        //errorStaticDto.setPercent("8.96");
        //list.add(errorStaticDto);

        errorStaticDto = new HomeErrorStaticDto();
        errorStaticDto.setNumber(21);
        errorStaticDto.setLabel("鸟粪");
        errorStaticDto.setPercent("14.48");
        list.add(errorStaticDto);

        errorStaticDto = new HomeErrorStaticDto();
        errorStaticDto.setNumber(15);
        errorStaticDto.setLabel("裂纹");
        errorStaticDto.setPercent("10.34");
        list.add(errorStaticDto);

        errorStaticDto = new HomeErrorStaticDto();
        errorStaticDto.setNumber(17);
        errorStaticDto.setLabel("紧固件丢失");
        errorStaticDto.setPercent("11.72");
        list.add(errorStaticDto);

        errorStaticDto = new HomeErrorStaticDto();
        errorStaticDto.setNumber(19);
        errorStaticDto.setLabel("其他异物");
        errorStaticDto.setPercent("13.1");
        list.add(errorStaticDto);

        return R.ok(list);
    }

    @Operation(summary = "首页-在线离线设备计算" , description = "在线离线设备计算" )
    @GetMapping("/robotOnlineStatic" )
    public R<RobotOnlineOrOffLineVo> onlineOrOffline() {
        RobotOnlineOrOffLineVo vo = new RobotOnlineOrOffLineVo();
        int offLineNumber = 0, onlineNumber = 0;
        List<RobotEntity> robotEntityList = robotService.list();
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        vo.setTotalNumber(robotEntityList.size());
        for (RobotEntity robotEntity : robotEntityList) {
            RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(robotEntity.getRobotSn());
            if (robotClientSummaryDto != null && robotClientSummaryDto.getStatus().getOnlineStatus() == 1) {
                onlineNumber ++;
            } else {
                offLineNumber ++;
            }
        }
        vo.setOnlineNumber(onlineNumber);
        vo.setOfflineNumber(offLineNumber);
        return R.ok(vo);
    }

    @Operation(summary = "首页-统计设备等总数量" , description = "在线离线设备计算" )
    @GetMapping(value = "countTotal")
    public R<HomeTotalCountVo>  countTotal() {
        HomeTotalCountVo homeTotalCountVo = new HomeTotalCountVo();
        homeTotalCountVo.setRobotNumber((int) robotService.count());
        homeTotalCountVo.setTotalTaskNumber((int) ticketsService.count());
        homeTotalCountVo.setCheckNumber((int) patrolResultService.count());
        homeTotalCountVo.setWarningNumber((int) robotWarningRecordService.count());
        return R.ok(homeTotalCountVo);
    }


    @Operation(summary = "首页-任务记录" , description = "任务记录" )
    @PostMapping("tickets")
    public R<List<HomeTicketsVo>> tickets(@RequestBody HomeTicketsParams params
    ) {

        List<HomeTicketsVo> homeTicketsVos = Lists.newArrayList();
        LambdaQueryWrapper<TicketsEntity> wrapper = Wrappers.lambdaQuery();
        if (StrUtil.isNotBlank(params.getStartDate())) {
            wrapper.gt(TicketsEntity::getCreateTime, params.getStartDate() + " 00:00:00");
        }
        if (StrUtil.isNotBlank(params.getEndDate())) {
            wrapper.le(TicketsEntity::getCreateTime, params.getEndDate() + " 00:00:00");
        }
        List<TicketsEntity> ticketsEntities = ticketsService.list(wrapper
                .orderByDesc(TicketsEntity::getId)
        );
        for (TicketsEntity ticketsEntity : ticketsEntities) {
            HomeTicketsVo homeTicketsVo = new HomeTicketsVo();
            homeTicketsVo.setStatus(ticketsEntity.getStatus());
            homeTicketsVo.setStatusStr("执行中");
            homeTicketsVo.setTaskName(ticketsEntity.getName());
            homeTicketsVo.setRobotName(ticketsEntity.getAllotRobotName());
            homeTicketsVo.setStartTime(ticketsEntity.getCreateTime());
            homeTicketsVo.setEndTime(ticketsEntity.getFinishTime());
            homeTicketsVos.add(homeTicketsVo);
        }
        return R.ok(homeTicketsVos);
    }


    @Operation(summary = "首页-任务与报警数量统计" , description = "任务与报警数量统计" )
    @PostMapping("ticketsAndWarningStatic")
    public R<List<DateAndStaticNumVo>> ticketsAndWarningStatic(@RequestBody SortByTypeParams params
    ) {
        List<DateAndStaticNumVo> tickets = Lists.newArrayList();
        Map<String, Long> warningBy = Maps.newHashMap();
        Map<String, Long> countTasksBy = Maps.newHashMap();
        if (Objects.equals(params.getSort(), "1")) {
            // 年
            List<TicketsEntity> ticketsEntities = ticketsService.list();
            List<RobotWarningRecordEntity> warningRecordEntities = robotWarningRecordService.list();
            countTasksBy = countTasksByYear(ticketsEntities);
            warningBy  = countWarningByYear(warningRecordEntities);
        } else if (Objects.equals(params.getSort(), "0")) {
            // 月
            List<TicketsEntity> ticketsEntities = ticketsService.list(Wrappers.<TicketsEntity>lambdaQuery()
                    .gt(TicketsEntity::getCreateTime, DateUtil.beginOfYear(DateUtil.date()).toJdkDate())
                    .lt(TicketsEntity::getCreateTime, DateUtil.endOfYear(DateUtil.date()).toJdkDate())
                    .orderByDesc(TicketsEntity::getCreateTime)
            );
            List<RobotWarningRecordEntity> warningRecordEntities = robotWarningRecordService.list(Wrappers.<RobotWarningRecordEntity>lambdaQuery()
                    .gt(RobotWarningRecordEntity::getTime, DateUtil.beginOfYear(DateUtil.date()).toJdkDate())
                    .lt(RobotWarningRecordEntity::getTime, DateUtil.endOfYear(DateUtil.date()).toJdkDate())
                    .orderByDesc(RobotWarningRecordEntity::getTime)
            );
            countTasksBy = countTasksByMonth(ticketsEntities);
            warningBy = countWarningByMonth(warningRecordEntities);
        }
        for (String s : countTasksBy.keySet()) {
            DateAndStaticNumVo dateAndStaticNumVo = new DateAndStaticNumVo();
            dateAndStaticNumVo.setDate(s);
            dateAndStaticNumVo.setTicketsNum(countTasksBy.get(s).intValue());
            dateAndStaticNumVo.setWarningNum(0);
            tickets.add(dateAndStaticNumVo);
        }
        for (String s : warningBy.keySet()) {
            Optional<DateAndStaticNumVo> optional = tickets.stream().filter(t-> t.getDate().equals(s)).findFirst();
            DateAndStaticNumVo vo = new DateAndStaticNumVo();
            vo.setDate(s);
            if (optional.isPresent()) {
                vo = optional.get();
                tickets.remove(vo);
            } else {
                vo.setTicketsNum(0);
            }
            vo.setWarningNum(warningBy.get(s).intValue());
            tickets.add(vo);
        }
        return R.ok(tickets);
    }



    private Map<String, Long> countTasksByMonth(List<TicketsEntity> taskList) {
        List<TransStaticDateDto> convertedTaskList = taskList.stream()
                .map(task -> new TransStaticDateDto(task.getName(),
                        DateUtil.date(task.getCreateTime()).toLocalDateTime().toLocalDate()))
                .collect(Collectors.toList());

        Map<String, List<TransStaticDateDto>> tasksByMonth =
                convertedTaskList.stream().collect(Collectors.groupingBy(
                        task -> task.getDate().getYear() + "-" + String.format("%02d", task.getDate().getMonthValue())));
        // 统计每个月分组后的任务数量
        return tasksByMonth.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> (long) entry.getValue().size()));
    }


    private Map<String, Long> countTasksByYear(List<TicketsEntity> taskList) {
        List<TransStaticYearDto> convertedTaskList = taskList.stream()
                .map(task -> new TransStaticYearDto(task.getName(),
                        DateUtil.date(task.getCreateTime()).toLocalDateTime().toLocalDate().getYear()))
                .collect(Collectors.toList());

        Map<String, List<TransStaticYearDto>> tasksByMonth =
                convertedTaskList.stream().collect(Collectors.groupingBy(
                        task -> "" + task.getYear()));
        // 统计每个月分组后的任务数量
        return tasksByMonth.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> (long) entry.getValue().size()));
    }

    private Map<String, Long> countWarningByMonth(List<RobotWarningRecordEntity> taskList) {
        List<TransStaticDateDto> convertedTaskList = taskList.stream()
                .map(task -> new TransStaticDateDto(task.getTitle(),
                        DateUtil.date(task.getTime()).toLocalDateTime().toLocalDate()))
                .collect(Collectors.toList());

        Map<String, List<TransStaticDateDto>> tasksByMonth =
                convertedTaskList.stream().collect(Collectors.groupingBy(
                        task -> task.getDate().getYear() + "-" + String.format("%02d", task.getDate().getMonthValue())));
        // 统计每个月分组后的任务数量
        return tasksByMonth.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> (long) entry.getValue().size()));
    }


    private Map<String, Long> countWarningByYear(List<RobotWarningRecordEntity> taskList) {
        List<TransStaticYearDto> convertedTaskList = taskList.stream()
                .map(task -> new TransStaticYearDto(task.getTitle(),
                        DateUtil.date(task.getTime()).toLocalDateTime().toLocalDate().getYear()))
                .collect(Collectors.toList());

        Map<String, List<TransStaticYearDto>> tasksByMonth =
                convertedTaskList.stream().collect(Collectors.groupingBy(
                        task -> "" + task.getYear()));
        // 统计每个月分组后的任务数量
        return tasksByMonth.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> (long) entry.getValue().size()));
    }


}
